package com.zengjianjun.base.log.appender;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.text.CharPool;
import com.zengjianjun.base.log.properties.BaseLogProperties;
import com.zengjianjun.base.log.utils.SpringUtil;
import com.zengjianjun.push.msg.enums.PushMsgTypeEnum;
import com.zengjianjun.push.msg.platform.PushMsgClient;
import com.zengjianjun.push.msg.platform.param.BasePushMsgParam;
import lombok.extern.slf4j.Slf4j;

import java.net.InetAddress;
import java.time.LocalDateTime;

/**
 * error级别日志报警通知
 *
 * @author zengjianjun
 */
@Slf4j
public class ErrorLogNoticeAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {

    @Override
    protected void append(ILoggingEvent eventObject) {
        try {
            BaseLogProperties baseLogProperties = SpringUtil.getBean(BaseLogProperties.class);
            if (baseLogProperties != null && baseLogProperties.isNoticeEnable()) {
                String msg = eventObject.getFormattedMessage();
                if (eventObject.getThrowableProxy() != null) {
                    msg = msg + "," + eventObject.getThrowableProxy().getMessage();
                }
                String stackTrace = stackTraceElementToString(eventObject.getCallerData());
                // 发送消息通知
                this.pushMsg(msg, stackTrace);
            }
        } catch (Throwable e) {
            log.warn("发送错误日志消息失败：", e);
        }
    }

    /**
     * 推送错误消息
     *
     * @param msg        错误信息
     * @param stackTrace 堆栈信息
     */
    private void pushMsg(String msg, String stackTrace) {
        try {
            StringBuilder sb = new StringBuilder();
            sb.append(">机器ip: ").append("<font color=\"info\">").append(InetAddress.getLocalHost().getHostAddress()).append("</font>").append(CharPool.LF)
                    .append(">错误时间: ").append("<font color=\"info\">").append(LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN)).append("</font>").append(CharPool.LF)
                    .append(">运行环境: ").append("<font color=\"info\">").append(SpringUtil.getActiveProfile()).append("</font>").append(CharPool.LF)
                    .append(">错误信息: ").append("<font color=\"comment\">").append(msg).append(CharPool.LF).append(stackTrace).append("</font>");
            BasePushMsgParam msgParam = BasePushMsgParam.builder()
                    .pushMsgTypeEnum(PushMsgTypeEnum.MARKDOWN)
                    .title(CharPool.BRACKET_START + SpringUtil.getEnvironment("spring.application.name") + CharPool.BRACKET_END + " 服务错误报警")
                    .content(sb.toString())
                    .build();
            PushMsgClient pushMsgClient = SpringUtil.getBean(PushMsgClient.class);
            if (pushMsgClient != null) {
                pushMsgClient.sendMsg(msgParam);
            } else {
                log.warn("未开启push-msg-spring-boot-starter");
            }
        } catch (Exception e) {
            log.warn("发送错误消息日志失败：", e);
        }
    }

    /**
     * 堆栈信息转成字符串
     *
     * @param stackTraceElements 堆栈信息
     * @return 堆栈信息
     */
    private String stackTraceElementToString(StackTraceElement[] stackTraceElements) {
        StringBuilder sb = new StringBuilder();
        if (stackTraceElements != null) {
            for (StackTraceElement stackTraceElement : stackTraceElements) {
                sb.append(stackTraceElement).append(CharPool.LF);
            }
        }
        return sb.toString();
    }
}
